package bl.tools;

import java.io.BufferedReader;
import java.io.FileReader;
import java.io.IOException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
import java.util.Map.Entry;

import ml.options.OptionSet;
import ml.options.Options;

public class LocCount {
	
	private static ArrayList<String> signatures = new ArrayList<String>();
	private static String in;  

	/**
	 * @param args
	 * @throws IOException 
	 */
	public static void main(String[] args) throws IOException {
		Options opt = new Options(args);
		opt.getSet().addOption("i", Options.Separator.BLANK,
							   Options.Multiplicity.ONCE).addOption("list", Options.Separator.BLANK,
							   Options.Multiplicity.ZERO_OR_ONE).addOption("ml",
							   Options.Separator.NONE, Options.Multiplicity.ZERO_OR_ONE).addOption("pp",
							   Options.Separator.NONE, Options.Multiplicity.ZERO_OR_ONE);
		OptionSet set = opt.getMatchingSet(true, false);
		
		if (set == null) {
			System.out.println("Usage:\n---------------------\n" +
					"\t-i \t file with size infos from LOCC\n"+
					"\t-list \t .ls file: signatures to count LOC\n");
			System.out.println("\nThe options library says:\n" + opt.getCheckErrors());
			System.exit(1);
		}
		
		in = set.getOption("i").getResultValue(0);
		String list = null;
//		if(set.isSet("list"))
//			list = set.getOption("list").getResultValue(0);
//		if(set.isSet("ml")){
//			if(list.substring(list.length() -3).equals("lst"))
//				listFile2ArrayList(list);
//			else
//				CSV2ArrayList(list);
//			System.out.println("\nLOGICAL LINES OF CODE in TOTAL: " + countLoc());
//		} else if(set.isSet("pp")) {
			listPackagesLoc();
		}
//	}
	
	private static void listPackagesLoc() throws NumberFormatException, IOException {
		LOCCParser lp = new LOCCParser(in);
		for(Iterator<Entry<String, Integer>> iter = lp.getPackageLoc().entrySet().iterator() ; iter.hasNext(); ){
			Map.Entry<String, Integer> entry = (Entry<String, Integer>) iter.next();
			System.out.println(entry.getKey() + ": " + entry.getValue());
		}
	}

	/**
	 * Gets an .ls File. Stores each line of that file to {@link signatures}.
	 * @param listFile input file
	 * @throws IOException
	 */
	private static void listFile2ArrayList(String listFile) throws IOException{
		FileReader fr = new FileReader(listFile);
		BufferedReader br = new BufferedReader(fr);
		String line;
		while(true){
			line = br.readLine();
			if(line != null)
				signatures.add(line);
			else
				break;
		}
	}
	
	private static void CSV2ArrayList(String listFile) throws IOException{
		FileReader fr = new FileReader(listFile);
		BufferedReader br = new BufferedReader(fr);
		String line;
		while(true){
			line = br.readLine();
			if(line != null){
				String tmp = line.split(";")[1];
				signatures.add(tmp.substring(0, tmp.indexOf('(')));
			}
			else
				break;
		}
	}
	
//	/**
//	 * Constructs a path out of signatures in {@link signatures}. Package information
//	 * in {@link signatures} is removed - method name and parameters are left.
//	 */
//	private static void setFilesToLookUp(){
//		String sig = "";
//		int fu = -1, i = 0, iClassNameEnd;
//		for(Iterator<String> iter = signatures.iterator(); iter.hasNext();){
//			sig = iter.next();
//			for(int j = 0; j < sig.length(); j++){
//				if( sig.substring(j, j+1).matches("[A-Z]") ){
//					fu = j;
//					break;
//				}
//			}
//			iClassNameEnd = sig.substring(fu).indexOf('.');
//			files.add(  sig.substring(0, fu).replace(".", ps) +
//						sig.substring(fu, fu + iClassNameEnd) +
//						".java"  );
//			signatures.set(i, sig.substring( fu + iClassNameEnd +1, sig.length()));
//			i++;
//		}
//	}
//	
//	/**
//	 * 
//	 * @return
//	 * @throws IOException 
//	 * @throws IOException 
//	 * @throws IOException
//	 */
//	private static int countLoc() throws IOException{
//		int loc = 0;
//		LOCCParser lp = new LOCCParser(in);
//		for(String signature : signatures){
//			loc += lp.getMethodLoc(signature);
//		}
//		return loc;
//	}
	
	/**
	 * 
	 * @return
	 * @throws IOException 
	 * @throws IOException 
	 * @throws IOException
	 */
	private static int countLoc() throws IOException{
		int loc = 0;
		LOCCParser lp = new LOCCParser(in);
		HashMap<String, Integer> methodsLoc = lp.getAllMethodsLOC(); 
		for(String signature : signatures){
			if(methodsLoc.containsKey(signature)){
				loc += methodsLoc.get(signature);
				System.out.println(loc + "\t" + signature);
			}
		}
		return loc;
	}

	
	/**
	 * Return the logical-LOC for the signature in the file given by the BufferedReader
	 * @param br BufferedReader for the file to read
	 * 		  signature the signature to look up
	 * @return logical-LOC for the given signature
	 * @throws IOException 
	 * TODO match several lines with function regexp
//	 */
//	private static int countMethodsLoc(BufferedReader br, String signature) throws IOException {
//		String re = makeSignatureRegExp(signature);
//		int loc = countRegExpLoc(br, re);
//		System.out.println(loc + "\t" + signature);
//		return loc;
//	}

//	public static int countRegExpLoc(BufferedReader br, String regExp) throws IOException{
//		String fileLine = "", line, java = "";
//		int loc, blocks = 1, offset = 0, end;
//		boolean withinComment = false;
//		
//		while( (line = br.readLine()) != null ){
//			java += line +"\n";
//		}
//		loc = 0;
//		Pattern pattern = Pattern.compile(regExp, Pattern.DOTALL); 
//		if(pattern.matcher(java).matches())
//			java = java.split(regExp)[1];
//		else
//			return 0;
//		int java_l = java.length();
//		while( true ){
//			while( offset < java_l && java.charAt(offset) == '\n' ){
//				offset++;
//			}
//			end = java.indexOf('\n', offset);
//			end = end != -1 ? end : java.length();
//			fileLine = java.substring(offset, end);
//			int comment = fileLine.indexOf("//");
//			if(comment != -1){
//				fileLine = fileLine.substring(0, comment);
//				end = java.indexOf('\n', offset);
//				end = end != -1 ? end : java.length();
//				offset += end - offset;
//			}
//			if( fileLine.matches(".*\\{.*") ) blocks++;
//			if( fileLine.matches(".*\\}.*") ) blocks--;
//			// take care that we are not within a multi line comment
//			if(fileLine.matches("/\\*")) withinComment = true;
//			if(fileLine.matches("\\*/")) withinComment = false;
//			// from here on increment only if we read a command or the begin of a block
//			if(  !withinComment && ( fileLine.matches(".*;.*") || fileLine.matches(".*\\w*\\(.*") )  )
//				loc++;
//			if( blocks ==  0 )
//				break;
//			offset += fileLine.length();
//		}
//		return loc;
//	}
//
//	private static String makeSignatureRegExp(String signature) {
//		String re = "(\\w\\s)*", qualiRe = "(\\w\\.)*", paramRe = "\\s+\\w+";
//		int ob = signature.indexOf('('), iSl;
//		re += signature.substring(0, ob) + "\\s*\\(\\s*"; // e.g. "methA(org.foo.goo"
//		signature = signature.substring(ob +1, signature.length() -1);
//		while(true){
//			iSl = signature.indexOf('/');
//			if(iSl == -1){
//				re += qualiRe + getUnqualified(signature, signature.length()) + paramRe + "\\s*\\)\\s*(\\w+\\s*)*\\{";
//				break;
//			}
//			re += qualiRe + getUnqualified(signature, iSl) + paramRe + ",\\s*";
//			signature = signature.substring(iSl +1, signature.length());
//		}
//		return re.replaceAll("\\[", "\\\\[").replaceAll("\\]", "\\\\]");
//	}
//	
//	private static String getUnqualified(String signature, int endPos){
//		int i = 0;
//		for(i = endPos -1; i > -1; i--){
//			String foo =signature.substring(i, i +1);
//			if(foo.equals("."))
//				break;
//		}
//		return signature.substring(i +1, endPos);
//	}

}
